import { BaseScraper, type ScrapingResult } from '../BaseScraper.js';
import type { DataSourceConfig, ScrapingStrategy } from '../types/ScraperConfig.js';
import { DataConverter, type ComponentData } from '../DataConverter.js';
import type { CheerioAPI } from 'cheerio';

/**
 * 通用组件抓取策略
 */
export class ComponentScrapingStrategy extends BaseScraper implements ScrapingStrategy {
  name = 'ComponentScrapingStrategy';

  constructor(private config: DataSourceConfig) {
    super(`${config.name}Scraper`, config.baseUrl);
    this.rateLimitDelay = config.scraping.rateLimitDelay;
    this.maxRetries = config.scraping.retry.maxRetries;
    this.retryDelay = config.scraping.retry.retryDelay;
  }

  matches(config: DataSourceConfig): boolean {
    return config.type === 'components' || config.type === 'charts';
  }

  async scrape(): Promise<ScrapingResult> {
    const startTime = Date.now();
    const result: ScrapingResult = {
      success: false,
      count: 0,
      data: [],
      errors: [],
      timestamp: new Date(),
      duration: 0,
    };

    try {
      this.log(`🚀 开始抓取 ${this.config.name} 数据...`);
      
      // 获取组件列表
      const componentUrls = await this.getComponentUrls();
      const totalComponents = componentUrls.length;
      
      this.emitProgress({
        stage: '获取组件列表',
        current: 0,
        total: 100,
        message: `发现 ${totalComponents} 个组件`,
      });

      const components: ComponentData[] = [];

      // 抓取每个组件的详细信息
      for (let i = 0; i < componentUrls.length; i++) {
        const componentUrl = componentUrls[i];
        if (!componentUrl) continue;
        
        this.emitProgress({
          stage: '抓取组件详情',
          current: i + 1,
          total: componentUrls.length,
          item: componentUrl.name,
          message: `正在抓取 ${componentUrl.name}...`,
        });

        try {
          const componentData = await this.scrapeComponent(componentUrl);
          if (componentData) {
            components.push(componentData);
            this.log(`✅ 成功抓取: ${componentData.name}`);
          }
        } catch (error) {
          const errorMsg = `抓取组件 ${componentUrl.name} 失败: ${error instanceof Error ? error.message : String(error)}`;
          result.errors.push(errorMsg);
          this.error(errorMsg);
        }

        // 遵守速率限制
        await this.delay(this.rateLimitDelay);
      }

      result.data = components;
      result.count = components.length;
      result.success = true;
      
      this.log(`🎉 抓取完成! 成功收集 ${components.length} 个组件`);

    } catch (error) {
      const errorMsg = `抓取过程发生错误: ${error instanceof Error ? error.message : String(error)}`;
      result.errors.push(errorMsg);
      this.error(errorMsg);
    }

    result.duration = Date.now() - startTime;
    return result;
  }

  /**
   * 获取组件URL列表
   */
  private async getComponentUrls(): Promise<Array<{ name: string; url: string; category: string }>> {
    const componentUrls: Array<{ name: string; url: string; category: string }> = [];

    try {
      // 如果是图表类型，使用预定义列表
      if (this.config.type === 'charts' && this.config.specific?.chartTypes) {
        for (const chartType of this.config.specific.chartTypes) {
          const url = this.config.scraping.detailPage.pathPattern.replace('{name}', chartType.toLowerCase());
          componentUrls.push({
            name: chartType,
            url: url,
            category: this.config.processing.categoryMapping[chartType] || '图表组件'
          });
        }
        
        this.log(`📋 从配置发现 ${componentUrls.length} 个组件`);
        return componentUrls;
      }

      // 尝试从列表页面抓取
      const listConfig = this.config.scraping.listPage;
      const paths = [listConfig.path, ...(listConfig.fallbackPaths || [])];

      for (const path of paths) {
        try {
          const html = await this.fetchPage(path);
          const $ = this.parseHtml(html);

          // 查找组件链接
          $(listConfig.itemSelector).each((_, element) => {
            const $item = $(element);
            const $link = $item.find(listConfig.linkSelector).first();
            const href = $link.attr('href');
            const name = this.extractName($, $item, listConfig.nameSelector);
            const category = this.extractCategory($, $item, listConfig.categorySelector);
            
            if (href && name) {
              componentUrls.push({
                name: this.normalizeComponentName(name),
                url: this.normalizeUrl(href),
                category: this.normalizeCategory(category)
              });
            }
          });

          if (componentUrls.length > 0) {
            this.log(`📋 从 ${path} 发现 ${componentUrls.length} 个组件`);
            break;
          }
        } catch (error) {
          this.warn(`从 ${path} 抓取列表失败: ${error instanceof Error ? error.message : String(error)}`);
        }
      }

      return this.deduplicateUrls(componentUrls);

    } catch (error) {
      this.error(`获取组件URL列表失败: ${error instanceof Error ? error.message : String(error)}`);
      return [];
    }
  }

  /**
   * 抓取单个组件的详细信息
   */
  private async scrapeComponent(componentInfo: { name: string; url: string; category: string }): Promise<ComponentData | null> {
    try {
      const html = await this.fetchPage(componentInfo.url);
      const $ = this.parseHtml(html);

      // 提取组件基本信息
      const title = this.extractTitle($) || componentInfo.name;
      const description = this.extractDescription($, componentInfo.name) || this.getDefaultDescription(componentInfo.name);
      
      // 提取API文档
      const props = this.extractProps($);
      const examples = this.extractExamples($);
      const imports = this.generateImports(componentInfo.name);

      const componentData: ComponentData = {
        name: componentInfo.name,
        category: componentInfo.category,
        title: title,
        description: description,
        documentation_url: this.normalizeUrl(componentInfo.url),
        api_reference: this.generateApiUrl(componentInfo.name),
        version: this.config.specific?.version || '5.x',
        tags: this.generateTags(componentInfo),
        props,
        examples,
        imports,
      };

      // 验证并修复数据完整性
      const validation = DataConverter.validateAndFixComponent(componentData);
      if (!validation.valid) {
        this.error(`组件 ${componentInfo.name} 数据无效: ${validation.errors.join(', ')}`);
        return null;
      }

      return validation.fixedData;

    } catch (error) {
      this.error(`抓取组件 ${componentInfo.name} 失败: ${error instanceof Error ? error.message : String(error)}`);
      return null;
    }
  }

  /**
   * 提取名称
   */
  private extractName($: CheerioAPI, $item: any, selector: string): string {
    const name = $item.find(selector).first().text() || $item.text();
    return this.cleanText(name);
  }

  /**
   * 提取分类
   */
  private extractCategory($: CheerioAPI, $item: any, selector?: string): string {
    if (!selector) return '';
    const category = $item.find(selector).first().text();
    return this.cleanText(category);
  }

  /**
   * 提取标题
   */
  private extractTitle($: CheerioAPI): string {
    const selectors = this.config.scraping.detailPage.titleSelectors;
    
    for (const selector of selectors) {
      const title = $(selector).first().text();
      if (title) {
        const cleanTitle = this.cleanText(title);
        if (cleanTitle) {
          return cleanTitle;
        }
      }
    }

    return '';
  }

  /**
   * 提取描述
   */
  private extractDescription($: CheerioAPI, componentName: string): string {
    const selectors = this.config.scraping.detailPage.descriptionSelectors;

    for (const selector of selectors) {
      const desc = $(selector).text();
      if (desc && desc.length > 10) {
        return this.cleanText(desc);
      }
    }

    return '';
  }

  /**
   * 提取属性
   */
  private extractProps($: CheerioAPI): Array<{ name: string; type: string; required: boolean; default_value?: string; description?: string }> {
    const props: Array<{ name: string; type: string; required: boolean; default_value?: string; description?: string }> = [];
    const selectors = this.config.scraping.detailPage.propsTableSelectors;

    for (const selector of selectors) {
      $(selector).find('tr').each((_, row) => {
        const $row = $(row);
        const cells = $row.find('td');
        
        if (cells.length >= 3) {
          const name = this.cleanText($(cells[0]).text());
          const type = this.cleanText($(cells[1]).text());
          const description = this.cleanText($(cells[2]).text());
          const defaultValue = cells.length > 3 ? this.cleanText($(cells[3]).text()) : undefined;
          
          if (name && type) {
            props.push({
              name,
              type,
              required: false, // 通常需要从文档中判断
              default_value: defaultValue,
              description
            });
          }
        }
      });
    }

    return props;
  }

  /**
   * 提取示例
   */
  private extractExamples($: CheerioAPI): Array<{ title: string; code: string; description?: string }> {
    const examples: Array<{ title: string; code: string; description?: string }> = [];
    const selectors = this.config.scraping.detailPage.codeSelectors;

    selectors.forEach((selector, index) => {
      $(selector).each((_, element) => {
        const code = $(element).text();
        if (code && code.length > 10) {
          examples.push({
            title: `示例 ${index + 1}`,
            code: DataConverter.formatCode(code),
            description: `${this.config.name} 使用示例`
          });
        }
      });
    });

    return examples;
  }

  /**
   * 生成导入信息
   */
  private generateImports(componentName: string): Array<{ import_path: string; import_name: string; is_default: boolean }> {
    const importConfig = this.config.processing.imports;
    const importName = importConfig.namePattern.replace('{name}', componentName);
    
    return [{
      import_path: importConfig.defaultPath,
      import_name: importName,
      is_default: importConfig.isDefault
    }];
  }

  /**
   * 生成API文档URL
   */
  private generateApiUrl(componentName: string): string {
    return this.normalizeUrl(`/docs/api/${componentName.toLowerCase()}`);
  }

  /**
   * 获取默认描述
   */
  private getDefaultDescription(componentName: string): string {
    const defaultDesc = this.config.processing.defaultDescriptions[componentName];
    if (defaultDesc) return defaultDesc;
    
    return DataConverter.generateDefaultDescription(componentName, this.config.type);
  }

  /**
   * 生成标签
   */
  private generateTags(componentInfo: { name: string; category: string }): string[] {
    const tags = new Set<string>();
    
    // 添加基础标签
    tags.add(this.config.type);
    if (componentInfo.category) {
      tags.add(componentInfo.category.toLowerCase());
    }

    // 根据规则生成标签
    for (const rule of this.config.processing.tagRules) {
      const target = rule.type === 'name' ? componentInfo.name : componentInfo.category;
      const pattern = typeof rule.pattern === 'string' ? new RegExp(rule.pattern, 'i') : rule.pattern;
      
      if (pattern.test(target)) {
        rule.tags.forEach(tag => tags.add(tag));
      }
    }

    return Array.from(tags);
  }

  /**
   * 规范化组件名称
   */
  private normalizeComponentName(name: string): string {
    return DataConverter.normalizeComponentName(name);
  }

  /**
   * 规范化分类
   */
  private normalizeCategory(category: string): string {
    if (!category) return '其他';
    
    const mapping = this.config.processing.categoryMapping;
    return mapping[category] || category;
  }

  /**
   * 去重URL列表
   */
  private deduplicateUrls(urls: Array<{ name: string; url: string; category: string }>): Array<{ name: string; url: string; category: string }> {
    const seen = new Set<string>();
    return urls.filter(url => {
      const key = url.name.toLowerCase();
      if (seen.has(key)) return false;
      seen.add(key);
      return true;
    });
  }
}